package cdu.sl.aop;

import cdu.sl.annotation.KeyAction;
import cdu.sl.entity.User;
import cdu.sl.enumeration.KeyActionType;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@RequiredArgsConstructor
@Component
@Aspect
public class LogAop {
    //  注入HttpServletRequest 以便获取Session
    private final HttpServletRequest httpServletRequest;
    // 操作人
    private User operator;

    // 自定义注解 在所有关键行为方法上加上此注解 方法操作会被记录到日志中
    // 切面表达式限定连接点为被KeyAction修饰的方法
    @Pointcut("execution(* *(..)) &&@annotation(cdu.sl.annotation.KeyAction)")
    public void keyMethod() {
    }

    // 方法执行之前获取会话中的用户数据
    @Before("keyMethod()")
    public void getUserInfo() {
        HttpSession session = httpServletRequest.getSession();
        operator = (User) session.getAttribute("userInfo");
    }

    @AfterReturning("keyMethod()")
    public void keyActionLog(JoinPoint joinPoint) throws Throwable {
        log.info("关键行为记录...");
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formatterDateTime = now.format(dateTimeFormatter);

        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        KeyAction keyAction = signature.getMethod().getAnnotation(KeyAction.class);

        KeyActionType keyActionType = keyAction.value();
        // 如果是登录操作 session中的userInfo数据为空 因此需要在登录操作完成后 才能获取到session中的userInfo数据
        if (keyActionType == KeyActionType.LOGIN) {
            HttpSession session = httpServletRequest.getSession();
            operator = (User) session.getAttribute("userInfo");
        }
        // 获取方法参数
        Object[] args = joinPoint.getArgs();

        switch (keyActionType) {
            case LOGIN:
                log.info("管理员：{}于{}登录系统", operator.getUsername(), formatterDateTime);
                break;
            case LOGOUT:
                log.info("管理员：{}于{}注销", operator.getUsername(), formatterDateTime);
                break;
            case EMP_INSERT:
                log.info("管理员：{}于{}新增员工 , 新增员工：{}", operator.getUsername(), formatterDateTime, args);
                break;
            case EMP_UPDATE:
                log.info("管理员：{}于{}修改员工, 修改详情:{}", operator.getUsername(), formatterDateTime, args);
                break;
            case EMP_DELETE:
                log.info("管理员：{}于{}删除员工 , 被删除员工id：{}", operator.getUsername(), formatterDateTime, args);
                break;
            case DEP_INSERT:
                log.info("管理员：{}于{}新增部门 , 新增部门：{}", operator.getUsername(), formatterDateTime, args);
                break;
            case DEP_UPDATE:
                log.info("管理员：{}于{}修改部门, 修改详情:{}", operator.getUsername(), formatterDateTime, args);
                break;
            case DEP_DELETE:
                log.info("管理员：{}于{}删除部门 , 被删除部门id：{}", operator.getUsername(), formatterDateTime, args);
                break;
        }
    }

}
